Generated code - Troubleshooting and debugging
Preface
Sometimes you want deep insight in what's really going on inside the runtime libraries, what SQL was generated and in what order did the queries
get executed, and not only during development, but also after deployment, when an application in production doesn't do what it should do. LLBLGen Pro
provides a fine-grained, robust tracing facility build on top of the .NET tracing functionality. See for more information about .NET tracing, the
.NET documentation on tracing: (opens online MSDN help)
Tracing and Instrumenting Applications in Visual Basic and Visual C#
.NET tracing offers easy to setup tracing which can be switched on and off by settings in the .config file of your application (app.config or web.config)
Note:
|
Tracing doesn't affect performance when all switches are switched off (the default) or not defined in the .config file.
Though when a switch is turned on, the tracing code will affect performance. Use the right switches for your tracing needs and leave them off
in production code or don't specify them at all, unless troubleshooting has to take place.
|
Note:
|
The traceswitch for the DQEs is a static (shared) switch as code shared among all DQE's is using the switch as well. This means
that if you're using simultaneously the DQEs of multiple databases, and you switch on tracing for one of the DQE's but not for the others, tracing won't
work as the switch will be turned off. Traceswitches have to be static/shared as the .NET tracing framework requires that. To avoid switching off the
traceswitch of the DQE you want tracing to be enabled, enable tracing of all DQEs used in your application. We'll change the internals of the tracing
framework as implemented in LLBLGen Pro's runtime library in the future to avoid this from happening. As the tracing is done by the .NET framework, this
is still a threadsafe operation.
|
Conventions
LLBLGen Pro's generated code offers two categories of tracing: info level and verbose level, and a variety of trace switches to switch tracing on or off. When a
trace switch is switched on, the runtime libraries will produce trace output, depending on which switch you've turned on and to which level: verbose or info.
This way you can keep the trace output small and still keep an eye on what's going on behind the scenes.
A trace listener can be defined in the .config file. If no trace listener is defined, and the application is started in debug mode from within VS.NET
(using F5), the tracing output will be delivered to the output window of VS.NET. This way, you can use the tracing functionality during development without leaving
the editor. .NET comes with some basic trace listeners, for example for writing the trace information to a file or to the event log. You can also write
trace listeners yourself. For more information see the online MSDN help link mentioned above.
Every method which has tracing functionality added, has a "Method Enter" and a "Method Exit" message. Most of the time these are logged at the info level,
though for methods which are called a lot, they're defined for the verbose level, so to see them, you have to switch on the particular trace switch at level
'4' (verbose). You can use these two messages for formatting/searching the trace output. When a method has multiple overloads, the number of
arguments is specified with a number, for example CreateDeleteDQ(3).
At the verbose level, LLBLGen Pro will report additional information, if applicable. For example the entity field information, parameter values and other
data which is only required when all information has to be retrieved. At the verbose level, all info level tracing is also provided.
All trace switches have to be defined in the .config file, in a system.Diagnostics tag, which has to be placed inside the configuration tag. You don't have
to define all switches, you can omit any switch definition if you'd like. When a switch isn't defined, it's considered turned off and no trace information
is produced which is tied to that switch. The following snippet shows all available trace switches. These switches are described in detail in the following
sections. The snippet below defines some switches with the value '3' (info level, switched on), '4' (verbose level, switched on) or '0' (switched off).
<system.diagnostics>
<switches>
<add name="SqlServerDQE" value="3" />
<add name="AccessDQE" value="4" />
<add name="OracleDQE" value="4" />
<add name="FirebirdDQE" value="4" />
<add name="MySqlDQE" value="4" />
<add name="DB2DQE" value="4" />
<add name="PostgreSqlDQE" value="4" />
<add name="SybaseAsaDQE" value="4" />
<add name="SybaseAseDQE" value="4" />
<add name="ORMGeneral" value="0" />
<add name="ORMStateManagement" value="0" />
<add name="ORMPersistenceExecution" value="3" />
<add name="LinqExpressionHandler" value="3" />
</switches>
</system.diagnostics>
Dynamic Query Engine tracing
To enable Dynamic Query Engine (DQE) tracing, you can for each different DQE switch it on to level 3 (info) or level 4 (verbose). To do that, you have to
make sure the switch for the DQE of the database you want trace information for is defined in the .config file, as shown in the previous section. The following
table shows the switches per database type.
DQE / database |
Trace switch |
SqlServer |
SqlServerDQE |
MS Access |
AccessDQE |
Oracle (ODP.NET/Microsoft Oracle Provider) |
OracleDQE |
Firebird |
FirebirdDQE |
MySQL |
MySqlDQE |
IBM DB2 |
DB2DQE |
PostgreSql |
PostgreSqlDQE |
Sybase ASA |
SybaseAsaDQE |
Sybase ASE |
SybaseAseDQE |
For all DQE's the levels 3 (info) and 4 (verbose) are supported and offer the same trace information. For each level, the trace information they'll
provide is listed below.
Info level tracing
When for a DQE, the trace switch is turned on to level 3 (info level), the following information is provided:
- Method Enter / Exit messages for the methods:
CreateInsertDQ, CreateDeleteDQ (and overloads), CreateUpdateDQ (and overloads),
CreateSelectDQ (and overloads), CreateRowCountDQ, CreateSubQuery.
Verbose level tracing
When for a DQE the trace switch is turned on to level 4 (verbose level), the following information is provided, besides the information provided
at the info level:
- Generated Sql Query messages for the methods:
CreateInsertDQ, CreateDeleteDQ (and overloads), CreateUpdateDQ (and overloads),
CreateSelectDQ (and overloads), CreateRowCountDQ. The Generated Sql Query contains the full SQL query and a listing of all parameters and their
values.
ORM Support classes tracing
The ORM Support classes offer three different switches to trace different functionality. These switches are described below:
- ORMGeneral switch for general code, like a collection Add method.
- ORMStateManagement switch for state management, like CheckForRefetch in SelfServicing
- ORMPersistenceExecution switch for persistence logic execution code, like FetchEntity. This is the switch you'll probably use the
most, in combination with a DQE switch to follow the complete call all the way to the database.
These three switches offer also the two levels supported: 3 for info level and 4 for verbose level. Below, per level per switch is described which
information is produced. Not every method in the ORM Support classes has tracing functionality. If you need tracing support for a method which doesn't
has tracing support at the moment, please send an email to
support@llblgen.com with your request.
Info level tracing
For the switch
ORMGeneral, the following information is provided when it is turned on to level 3:
- Method Enter / Exit messages for the methods:
EntityBase.Entity2Xml, EntityBase2.Entity2Xml, EntityCollectionBase.Insert,
EntityCollectionBase.Remove, EntityCollectionBase.RemoveAt, EntityCollectionBase.OnClear, EntityCollectionBase.Sort(3),
EntityCollectionBase.EntityCollection2Xml, EntityCollectionBase.Xml2EntityCollection, EntityCollectionBase2.Insert,
EntityCollectionBase2.Remove, EntityCollectionBase2.RemoveAt, EntityCollectionBase2.OnClear, EntityCollectionBase2.Sort(3),
EntityCollectionBase2.EntityCollection2Xml, EntityCollectionBase2.Xml2EntityCollection
For the switch
ORMStateManagement, the following information is provided when it is turned on to level 3:
- Method Enter / Exit messages for the methods:
EntityBase.Validate, EntityBase2.Validate
For the switch
ORMPersistenceExecution, the following information is provided when it is turned on to level 3:
- Method Enter / Exit messages for the methods:
DaoBase.ExecuteActionQuery, DaoBase.ExecuteSingleRowRetrievalQuery, DaoBase.ExecuteMultiRowRetrievalQuery, DaoBase.ExecuteMultiRowDataTableRetrievalQuery(3),
DaoBase.ExecuteScalarQuery, DaoBase.FetchPrefetchPath, DaoBase.MergeNormal, DaoBase.MergeNormal, DataAccessAdapterBase.GetScalar(6),
DataAccessAdapterBase.GetScalar(4), DataAccessAdapterBase.GetDbCount(4), DataAccessAdapterBase.ExecuteScalarQuery,
DataAccessAdapterBase.ExecuteActionQuery, DataAccessAdapterBase.ExecuteSingleRowRetrievalQuery, DataAccessAdapterBase.ExecuteMultiRowRetrievalQuery,
DataAccessAdapterBase.ExecuteMultiRowDataTableRetrievalQuery(3), DataAccessAdapterBase.StartTransaction, DataAccessAdapterBase.Commit,
DataAccessAdapterBase.Rollback, DataAccessAdapterBase.OpenConnection, DataAccessAdapterBase.CloseConnection, DataAccessAdapterBase.SaveEntity(4),
DataAccessAdapterBase.FetchEntity(1), DataAccessAdapterBase.FetchEntity(3), DataAccessAdapterBase.FetchEntityUsingUniqueConstraint(2),
DataAccessAdapterBase.FetchEntityUsingUniqueConstraint(4), DataAccessAdapterBase.FetchEntityUsingUniqueConstraint(4),
DataAccessAdapterBase.FetchNewEntity(4), DataAccessAdapterBase.DeleteEntity(1), DataAccessAdapterBase.DeleteEntity(2),
DataAccessAdapterBase.FetchEntityCollection(3), DataAccessAdapterBase.FetchEntityCollection(5), DataAccessAdapterBase.FetchEntityCollection(6),
DataAccessAdapterBase.SaveEntityCollection(3), DataAccessAdapterBase.DeleteEntityCollection, DataAccessAdapterBase.DeleteEntitiesDirectly,
DataAccessAdapterBase.FetchTypedList(9), DataAccessAdapterBase.SaveTransaction, DataAccessAdapterBase.Rollback(1),
DataAccessAdapterBase.FetchEntityUsingFilter(3), DataAccessAdapterBase.FetchEntityUsingFilter, DataAccessAdapterBase.FetchEntityUsingFilter(4),
DataAccessAdapterBase.UpdateEntitiesDirectly, EntityBase.Save(2), EntityCollectionBase.SaveMulti, EntityCollectionBase.DeleteMulti,
Query.ReflectOutputValuesInRelatedFields, TransactionBase.CTor(2), TransactionBase.CTor, TransactionBase.CTor(3), TransactionBase.Commit,
TransactionBase.Rollback, TransactionBase.Save, TransactionComPlusBase.CTor(1), TransactionComPlusBase.Commit, TransactionComPlusBase.Rollback,
UnitOfWork.Commit(2), UnitOfWork2.Commit(2)
Verbose level tracing
For the switch
ORMGeneral, the following information is provided when it is turned on to level 4, besides the information provided
for level 3:
- Method Enter / Exit messages for the methods:
EntityCollectionBase.Add, EntityCollectionBase2.Add
- Information about used entity objects, return values and parameters for the methods:
EntityCollectionBase.Add, EntityCollectionBase2.Ad, EntityCollectionBase.Insert, EntityCollectionBase2.Insert,
EntityCollectionBase.Remove, EntityCollectionBase2.Remove, EntityCollectionBase.RemoveAt, EntityCollectionBase2.RemoveAt
For the switch
ORMStateManagement, the following information is provided when it is turned on to level 4, besides the information provided
for level 3:
- Method Enter / Exit messages for the methods:
EntityBase.CheckForRefetch, EntityBase.SyncFKFields, EntityBase.ValidateValueCustom, EntityBase2.SyncFKFields, EntityBase2.ValidateValueCustom
- Information about used entity objects, return values and parameters for the methods:
EntityBase.Validate, EntityBase.SyncFKFields, EntityBase.ValidateValueCustom,
EntityBase2.Validate, EntityBase2.SyncFKFields, EntityBase2.ValidateValueCustom
For the switch
ORMPersistenceExecution, the following information is provided when it is turned on to level 4, besides the information provided
for level 3:
- Method Enter / Exit messages for the methods:
DataAccessAdapterBase.Reset, DataAccessAdapterBase.FetchPrefetchPath, DataAccessAdapterBase.MergeNormal, DataAccessAdapterBase.MergeManyToMany,
TransactionBase.Reset, TransactionComPlusBase.Reset, UnitOfWork.Reset, UnitOfWork2.Reset
- Information about used entity objects, return values, internal activity and parameters for the methods:
DaoBase.ExecuteActionQuery, DataAccessAdapterBase.StartTransaction, DataAccessAdapterBase.SaveEntity(4),
DataAccessAdapterBase.FetchEntity(1), DataAccessAdapterBase.FetchEntity(3), DataAccessAdapterBase.FetchEntityUsingUniqueConstraint,
DataAccessAdapterBase.DeleteEntity(1), DataAccessAdapterBase.DeleteEntity(2), DataAccessAdapterBase.FetchEntityCollection(6),
DataAccessAdapterBase.SaveEntityCollection(3), DataAccessAdapterBase.DeleteEntityCollection, DataAccessAdapterBase.DeleteEntitiesDirectly,
DataAccessAdapterBase.UpdateEntitiesDirectly, DataAccessAdapterBase.SaveTransaction, DataAccessAdapterBase.Rollback(1),
EntityBase.Save(2), Query.ReflectOutputValuesInRelatedFields, TransactionBase.CTor(2), TransactionBase.CTor(3), TransactionBase.Save,
TransactionBase.Rollback(1), UnitOfWork.Commit(2), UnitOfWork2.Commit(2)
- Query executed messages when a query is executed in the methods listed above. The query executed including parameters and full SQL is
mentioned in the output
Linq to LLBLGen Pro tracing
The Linq to LLBLGen Pro provider also supports tracing. It has two levels: Info level tracing (3), which is recommended if this tracer is used, and Verbose level tracing (4). Info level tracing emits the expression tree into the output in textual form. This is useful to get more information about what was exactly passed to the Linq provider. Verbose level tracing is
really verbose: it emits a complete visit trace of all methods called during the handling of the linq query. In general this isn't recommended as it eats a lot of performance and also emits a lot of output. Only use level 4 for this tracer if you absolutely have to.
Debugger Visualizers
Starting with VS.NET 2005, Visual Studio offers the ability to enable visualizer objects for given types during debugging sessions called
Debugger visualizers. If you've already
done some debugging inside VS.NET 2005 or VS.NET 2008 you've seen some of them already: the string debugger visualizer for example is one of the debugger visualizers shipped
with VS.NET which can be activated when the execution is paused and you hover over a type with the mouse and click the magnifyer glass icon.
For several types in the LLBLGen Pro generated code and runtime library, Debugger Visualizers are developed so debugging code using LLBLGen Pro generated
code is easier.
Installation
Copy the SD.LLBLGen.Pro.DebugVisualizers.dll from the folder
Frameworks\LLBLGen Pro\RuntimeLibraries\DebuggerVisualizers\
xxyy\ to the folder:
My Documents\Visual Studio
xxyy\Visualizers\
Also copy the ORMSupportClasses dll and the DQE dll of your choice to that folder.
'
xxyy' is the vs.net year number of the vs.net version you're using.
You need to restart VS.NET to make them available to you. In a debug session, when you hit a breakpoint, you can hover your mouse over a variable of a type of
any of the supported types below and you'll see a magnifyer glass which allows you to open the debug visualizer for that type with the data in that instance.
Debug visualizers included
The following debug visualizers are included:
Predicate/PredicateExpression
The predicate / Predicate expression visualizer visualizes the predicate as a WHERE clause. It will use a pseudo DQE and pseudo DB specific creator to
create a string which is displayed in a viewer. Also displayed are the parameters of the complete filter and the values of these parameters.
EntityCollection (Selfservicing/adapter)
Simple form with a DataGrid set to readonly/AllowNavigation set to false (to avoid lazy loading) for SelfServicing entity collections and with AllowNavigation
set to true for Adapter, which displays the collection using normal databinding. The form also shows a textbox
with the type the collection is set for, which is typically the type the factory produces.
RelationCollection / Relationpredicatebucket
Similar to PredicateExpression, though it will show the actual SQL generated. The RelationPredicateBucket visualizer has a tab control with both a
visualizer for the PredicateExpression as for the RelationCollection.
SortExpression
Simple visualizer which shows the sort expression in a textbox, similar to the predicate expression visualizer
GroupByCollection
Simple viewer which views the grouped fields, one on each line and the HAVING clause as a normal predicate expression.
PrefetchPath
The visualizer for prefetch paths displays the path as nodes in a tree. To handle polymorphic paths, the path element is represented by a node,
and all nodes added to that path element are added as nodes. The visualizer uses reflection to get a hold on the EntityType type definition to
produce proper names for the node destinations/types to fetch.
Expression
The visualizer for the expression is similar to the PredicateVisualizer: it shows the expression without beautification and the parameters.